/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package controller;

/**
 *
 * @author ΠΑΝΑΓΙΩΤΗΣ v1
 */
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.*;
import supermarketv0_class.*;
import supermarketv1.PurchasingSimulation;


import java.io.File;
import java.text.NumberFormat;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

public class SuperMarket_v6 {

    private EntityManagerFactory emf;
    private EntityManager em;
    private ArrayList<Store> stores;
    private ArrayList<Product> products;
    private ArrayList<Customer> customers;
    private int customersNum;
    private int purchaseNum;
    private int storenum;
    private int productnum;
    private int productPurchaseNum;
    private int checksnum;
    private int cardnum;
    PurchasingSimulation ps;
    String filePath = "D:" + File.separator + "purchases.xml";

    public SuperMarket_v6() {
        emf = Persistence.createEntityManagerFactory("SuperMarketv1PU");
        em = emf.createEntityManager();
        //clearDB();
        File file = new File(filePath);
        file.delete();
        stores = new ArrayList();
        products = new ArrayList();
        customers = new ArrayList();
    }

    public void readFromXML() {
     try {
     File fXmlFile = new File(filePath);
     DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
     DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
     Document doc = dBuilder.parse(fXmlFile);

     doc.getDocumentElement().normalize();


     NodeList nList = doc.getElementsByTagName("Purchase");

     double totalAmount = 0;

     for (int temp = 0; temp < nList.getLength(); temp++) {

     Node nNode = nList.item(temp);

     if (nNode.getNodeType() == Node.ELEMENT_NODE) {
     Element eElement = (Element) nNode;
     totalAmount += Double.parseDouble(eElement.getElementsByTagName("amount").item(0).getTextContent());
     }
     }
     System.out.println("Μέση τιμή αγορών:" + (totalAmount / nList.getLength()));
     } catch (Exception e) {
     e.printStackTrace();
     }
     }
    public void exportToXML() {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            File f = new File(filePath);
            if (!f.exists()) {

                Document doc = docBuilder.newDocument();
                Element rootElement = doc.createElement("purchases");
                doc.appendChild(rootElement);

                List purchases = readPurchases();

                Iterator itr = purchases.iterator();

                while (itr.hasNext()) {
                    Purchase p = (Purchase) itr.next();
                    // staff elements
                    Element purchase = doc.createElement("Purchase");
                    rootElement.appendChild(purchase);

                    // set attribute to staff element
                    Attr attr = doc.createAttribute("id");
                    attr.setValue("" + p.getPurchaseId());
                    purchase.setAttributeNode(attr);

                    // shorten way
                    // purchase.setAttribute("id", ""+p.getPurchaseId());

                    // firstname elements
                    Element date = doc.createElement("date");
                    String dateString = p.getDatetime().getDate() + "/" + (p.getDatetime().getMonth() + 1) + "/" + p.getDatetime().getYear() + " " + p.getDatetime().getHours() + ":" + p.getDatetime().getMinutes() + ":" + p.getDatetime().getSeconds();
                    date.appendChild(doc.createTextNode(dateString));
                    purchase.appendChild(date);

                    Element amount = doc.createElement("amount");
                    amount.appendChild(doc.createTextNode(p.getAmount() + ""));
                    purchase.appendChild(amount);

                    Element points_earned = doc.createElement("points_earned");
                    points_earned.appendChild(doc.createTextNode(p.getPointsEarned() + ""));
                    purchase.appendChild(points_earned);

                    Element delivery = doc.createElement("delivery");
                    delivery.appendChild(doc.createTextNode(p.getDelivery() + ""));
                    purchase.appendChild(delivery);

                    Element store = doc.createElement("store");
                    store.appendChild(doc.createTextNode(p.getStore().getName()));
                    purchase.appendChild(store);


                    Element customer = doc.createElement("customer");
                    customer.appendChild(doc.createTextNode(p.getCustomer().getLastName() + " " + p.getCustomer().getFirstName()));
                    purchase.appendChild(customer);

                    Element retries = doc.createElement("rerties");
                    retries.appendChild(doc.createTextNode(" " + ps.getCounter()));
                    purchase.appendChild(retries);

                    Element name = doc.createElement("Thread");
                    name.appendChild(doc.createTextNode("" + ps.getNamethread()));
                    purchase.appendChild(name);



                }

                // write the content into xml file

                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);

                StreamResult resultXML = new StreamResult(f);
                transformer.transform(source, resultXML);

            } else {
                Document doc = docBuilder.parse(f);

                // Get the root element
                Node rootElement = doc.getFirstChild();


                List purchases = readPurchases();

                Iterator itr = purchases.iterator();

                while (itr.hasNext()) {
                    Purchase p = (Purchase) itr.next();
                    // staff elements
                    Element purchase = doc.createElement("Purchase");
                    rootElement.appendChild(purchase);

                    // set attribute to staff element
                    Attr attr = doc.createAttribute("id");
                    attr.setValue("" + p.getPurchaseId());
                    purchase.setAttributeNode(attr);

                    // shorten way
                    // purchase.setAttribute("id", ""+p.getPurchaseId());

                    // firstname elements
                    Element date = doc.createElement("date");
                    String dateString = p.getDatetime().getDate() + "/" + (p.getDatetime().getMonth() + 1) + "/" + p.getDatetime().getYear() + " " + p.getDatetime().getHours() + ":" + p.getDatetime().getMinutes() + ":" + p.getDatetime().getSeconds();
                    date.appendChild(doc.createTextNode(dateString));
                    purchase.appendChild(date);

                    Element amount = doc.createElement("amount");
                    amount.appendChild(doc.createTextNode(p.getAmount() + ""));
                    purchase.appendChild(amount);

                    Element points_earned = doc.createElement("points_earned");
                    points_earned.appendChild(doc.createTextNode(p.getPointsEarned() + ""));
                    purchase.appendChild(points_earned);

                    Element delivery = doc.createElement("delivery");
                    delivery.appendChild(doc.createTextNode(p.getDelivery() + ""));
                    purchase.appendChild(delivery);

                    Element store = doc.createElement("store");
                    store.appendChild(doc.createTextNode(p.getStore().getName()));
                    purchase.appendChild(store);


                    Element customer = doc.createElement("customer");
                    customer.appendChild(doc.createTextNode(p.getCustomer().getLastName() + " " + p.getCustomer().getFirstName()));
                    purchase.appendChild(customer);

                    Element retries = doc.createElement("rerties");
                    retries.appendChild(doc.createTextNode(" " + ps.getCounter()));
                    purchase.appendChild(retries);

                    Element name = doc.createElement("Thread");
                    name.appendChild(doc.createTextNode("" + ps.getNamethread()));
                    purchase.appendChild(name);

                }
                // write the content into xml file
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);
                StreamResult resultXML = new StreamResult(f);
                transformer.transform(source, resultXML);
            }
          //  clearDBPurchases();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

 
    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }
    //-------

    public List readStores() {//μέθοδος ανάγνωσης καταστημάτων 

        em.getTransaction().begin();

        try {
            Query q = em.createQuery("SELECT s FROM Store s ", Store.class);
            List result = q.getResultList();

            em.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }

    public boolean readStoreID() {
        em.getTransaction().begin();
        boolean x = false;
        try {

            Query q1 = em.createQuery("SELECT  c FROM Store c ", Store.class);
            Store pu = (Store) q1.getResultList();
            Iterator itr = q1.getResultList().iterator();
            if (itr.hasNext()) {
                x = true;
                return x;

            } else {
                x = false;
            }


            em.getTransaction().commit();
        } catch (Exception e) {

            em.getTransaction().rollback();

        }
        return x;
    }

    public void NewStore(String name, String address, List s) {//νέο κατάστημα

        em.getTransaction().begin();
        try {//
            if (s.isEmpty()) {
                storenum++;
            } else {
                Query q1 = em.createQuery("SELECT MAX (c.storeId ) FROM Store c ", Store.class);
                int pu = (Integer) q1.getSingleResult();
                storenum = pu + 1;
            }


            Store store = new Store();
            store.setStoreId(storenum);
            store.setName(name);
            store.setAddress(address);
            em.persist(store);

            em.getTransaction().commit();

        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();
        }
    }

    public void ModifyStore(Store store, String name, String address) {
        em.getTransaction().begin();
        try {
            store.setName(name);
            store.setAddress(address);
            em.merge(store);

            em.getTransaction().commit();
        } catch (Exception ex) {
            em.getTransaction().rollback();
        }
    }

    public void DeleteStore(Store store) {
        em.getTransaction().begin();
        try {
            System.out.println(store.getStoreId());
            int deletedCount = em.createQuery("DELETE FROM Store s WHERE s.storeId='" + store.getStoreId() + "'", Store.class).executeUpdate();

            em.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();
        }
    }
    //------------

    public boolean readProductID() {
        em.getTransaction().begin();
        boolean x = false;
        try {

            Query q1 = em.createQuery("SELECT p FROM Product p ", Product.class);
            Product pu = (Product) q1.getResultList();
            if (pu == null) {
                return x;
            } else {
                x = true;
            }


            em.getTransaction().commit();
        } catch (Exception e) {

            em.getTransaction().rollback();
            return x;
        }
        return x;
    }

    public List readProduct() {

        em.getTransaction().begin();

        try {
            Query q = em.createQuery("SELECT p FROM Product p ", Product.class);
            List result = q.getResultList();

            em.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }

    public void NewProduct(String name, String code, int points, float price, List s) {
        em.getTransaction().begin();
        try {//
            if (s.isEmpty()) {
                productnum++;
            } else {
                Query q1 = em.createQuery("SELECT MAX (c.productId ) FROM Product c ", Product.class);
                int pu = (Integer) q1.getSingleResult();
                productnum = pu + 1;
            }

            Product product = new Product();

            product.setProductId(productnum);
            product.setName(name);
            product.setCode(code);
            product.setPoints(points);
            product.setPrice(price);
            em.persist(product);

            em.getTransaction().commit();

        } catch (Exception ex) {
            //ex.printStackTrace();
            em.getTransaction().rollback();

        }
    }

    public void ModifyProduct(Product product, String name, String code, int points, float price) {
        em.getTransaction().begin();
        try {
            product.setName(name);
            product.setCode(code);
            product.setPoints(points);
            product.setPrice(price);
            em.merge(product);

            em.getTransaction().commit();
        } catch (Exception ex) {
            em.getTransaction().rollback();
        }
    }

    public void DeleteProduct(Product product) {
        em.getTransaction().begin();
        try {

            int deletedCount = em.createQuery("DELETE FROM Product p WHERE p.productId='" + product.getProductId() + "'", Product.class).executeUpdate();

            em.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();
        }
    }
    //----

    public Customer getCustomer(String pas) {
        Customer cust = new Customer();
        em.getTransaction().begin();
        try {
            Query q = em.createQuery("SELECT c FROM Customer c WHERE "
                    + "c.codepass='" + pas + "'", Customer.class);
            Customer resultC = (Customer) q.getSingleResult();
            cust = resultC;
            em.getTransaction().commit();
        } catch (Exception e) {
            // e.printStackTrace();
            em.getTransaction().rollback();
        }
        return cust;

    }

    public Customer getCustomer(int pas) {
        Customer cust = new Customer();
        em.getTransaction().begin();
        try {
            Query q = em.createQuery("SELECT c FROM Customer c WHERE "
                    + "c.pointsCardNumber='" + pas + "'", Customer.class);
            Customer resultC = (Customer) q.getSingleResult();
            cust = resultC;
            em.getTransaction().commit();
        } catch (Exception e) {
            // e.printStackTrace();
            em.getTransaction().rollback();
        }
        return cust;

    }

    public List readCustomers() {
        em.getTransaction().begin();

        try {
            Query q = em.createQuery("SELECT c FROM Customer c ", Customer.class);
            List result = q.getResultList();

            em.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }

    public boolean readCustomerID() {
        em.getTransaction().begin();
        boolean x = false;
        try {

            Query q1 = em.createQuery("SELECT  c FROM Customer c ", Customer.class);
            Purchase pu = (Purchase) q1.getResultList();
            if (pu == null) {
                return x;
            } else {
                x = true;
            }


            em.getTransaction().commit();
        } catch (Exception e) {

            em.getTransaction().rollback();
            return x;
        }
        return x;
    }

    public void NewCustomer(String fname, String lname, String address, String codepass, int cardnum, List s) {
        em.getTransaction().begin();
        try {//
            if (s.isEmpty()) {
                customersNum++;
            } else {
                Query q1 = em.createQuery("SELECT MAX (c.customerId ) FROM Customer c ", Customer.class);
                int pu = (Integer) q1.getSingleResult();
                customersNum = pu + 1;
            }
            Customer customer = new Customer();
            customer.setCustomerId(customersNum);
            customer.setFirstName(fname);
            customer.setLastName(lname);
            customer.setAddress(address);
            customer.setCodepass(codepass);
            customer.setPointsCardNumber(cardnum);

            em.persist(customer);

            em.getTransaction().commit();

        } catch (Exception ex) {
            //ex.printStackTrace();
            em.getTransaction().rollback();

        }
    }

    public void ModifyCustomer(Customer customer, String fname, String lname, String address, String codepass) {
        em.getTransaction().begin();
        try {
            customer.setFirstName(fname);
            customer.setLastName(lname);
            customer.setAddress(address);
            customer.setCodepass(codepass);
            em.merge(customer);

            em.getTransaction().commit();
        } catch (Exception ex) {
            em.getTransaction().rollback();
        }
    }

    public void ModifyCustomer(Customer customer, String fname, String lname, String address) {
        em.getTransaction().begin();
        try {
            customer.setFirstName(fname);
            customer.setLastName(lname);
            customer.setAddress(address);
            em.merge(customer);

            em.getTransaction().commit();
        } catch (Exception ex) {
            em.getTransaction().rollback();
        }
    }

    public void ModifyPassWord(Customer customer, String pass) {
        em.getTransaction().begin();
        try {
            customer.setCodepass(pass);

            em.merge(customer);

            em.getTransaction().commit();
        } catch (Exception ex) {
            //   em.getTransaction().rollback();
        }
    }

    public void DeleteCustomer(Customer customer) {
        em.getTransaction().begin();
        try {

            int deletedCount = em.createQuery("DELETE FROM Customer c WHERE c.customerId='" + customer.getCustomerId() + "'", Customer.class).executeUpdate();

            em.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();
        }
    }

    //---
    public void RelationStoreProduct(ArrayList<Store> store, ArrayList<Product> product) {
        em.getTransaction().begin();
        try {
            ArrayList<Store> col1 = new ArrayList();
            col1.add(store.get(0));
            for (int i = 0; i < product.size(); i++) {
                product.get(i).setStoreList(col1);
                store.get(0).setProductList(product);
                em.persist(product.get(i));

            }

            em.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }


    }

    public void makePurchase(Customer c, Store s, Product p, int q, List si, boolean del) {
        em.getTransaction().begin();
        try {

            if (si.isEmpty()) {//αν είναι η πρώτη εγγραφή στον πίνακα
                purchaseNum++;
                productPurchaseNum++;

            } else {//βρες την τελευταια εγγραφή 

                Query q1 = em.createQuery("SELECT MAX (p.purchaseId ) FROM Purchase p ", Purchase.class);
                Query q2 = em.createQuery("SELECT MAX (p.productPurchaseId ) FROM ProductPurchase p ", ProductPurchase.class);
                int pur = (Integer) q2.getSingleResult();
                int pu = (Integer) q1.getSingleResult();
                productPurchaseNum = pur + 1;
                purchaseNum = pu + 1;


            }

            Purchase purchase = new Purchase();
            purchase.setPurchaseId(purchaseNum);
            purchase.setDatetime(new Date());
            purchase.setCustomer(c);
            purchase.setStore(s);
            purchase.setAmount((float) 0.0);
            purchase.setPointsEarned(0);
            purchase.setDelivery(false);


            c.setAvailablePoints(0);

            ProductPurchase productPurchase = new ProductPurchase();
            ArrayList<ProductPurchase> pp = new ArrayList();
            productPurchase.setProductPurchaseId(productPurchaseNum);
            productPurchase.setProductId(p);
            productPurchase.setQuality(q);
            productPurchase.setPurchaseId(purchase);
            pp.add(productPurchase);

            int l = (int) (Math.round(p.getPrice()));
            purchase.setAmount(purchase.getAmount() + (l * q));
            int points = (int) purchase.getPointsEarned() + p.getPoints() * q;
            purchase.setPointsEarned(points);
            if (del == true) {
                purchase.setDelivery(true);
            }

            c.setAvailablePoints((Integer) c.getAvailablePoints() + purchase.getPointsEarned());

            em.merge(c);

            em.persist(purchase);
            em.persist(productPurchase);


            em.getTransaction().commit();
        } catch (Exception e) {
            System.out.println(e);
            em.getTransaction().rollback();
        }

    }

    public List readPurchases() {
        em.getTransaction().begin();

        try {

            Query q1 = em.createQuery("SELECT  p FROM Purchase p ", Purchase.class);
            List result = q1.getResultList();

            em.getTransaction().commit();
            return result;
        } catch (Exception e) {

            em.getTransaction().rollback();

        }
        return null;
    }

    public List readPurchase(Customer c) {
        em.getTransaction().begin();

        try {
            Query q = em.createQuery("SELECT p FROM Purchase p WHERE p.customer.customerId='" + c.getCustomerId() + "'", Purchase.class);
            List result = q.getResultList();

            em.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;

    }

    public ProductPurchase getProductPurchase(Purchase purchase) {
        em.getTransaction().begin();

        try {
            Query q = em.createQuery("SELECT p FROM ProductPurchase p WHERE p.purchaseId='" + purchase.getPurchaseId() + "'", ProductPurchase.class);
            ProductPurchase result = (ProductPurchase) q.getSingleResult();

            em.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }
//------

    public boolean readCheckID() {
        em.getTransaction().begin();
        boolean x = false;
        try {

            Query q1 = em.createQuery("SELECT  c FROM Checks c ", Checks.class);
            Checks pu = (Checks) q1.getResultList();
            if (pu == null) {
                return x;
            } else {
                x = true;
            }


            em.getTransaction().commit();
        } catch (Exception e) {

            em.getTransaction().rollback();
            return x;
        }
        return x;
    }

    public void newCheck(Customer c, List s) {
        em.getTransaction().begin();

        try {
            if (s.isEmpty()) {
                checksnum++;

            } else {
                Query q2 = em.createQuery("SELECT MAX (c.checkId ) FROM Checks c ", Checks.class);
                int pur = (Integer) q2.getSingleResult();

                checksnum = pur + 1;
            }

            Checks check = new Checks();
            check.setCheckId(checksnum);
            check.setDatetime(new Date());
            check.setValidity("Available");
            check.setAmount(6);
            check.setCustomerid(c.getCustomerId());
            em.persist(check);


            em.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }

    }

    public List readChecks() {
        em.getTransaction().begin();

        try {
            Query q = em.createQuery("SELECT c FROM Checks c ", Checks.class);
            List result = q.getResultList();

            em.getTransaction().commit();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }

    public ArrayList readCheckOK(Customer c) {
        em.getTransaction().begin();

        try {
            ArrayList che = new ArrayList();
            Query q = em.createQuery("SELECT c FROM Checks c Where c.customerid='" + c.getCustomerId() + "'", Checks.class);
            List result = q.getResultList();
            Iterator itr = result.iterator();
            while (itr.hasNext()) {
                Checks ch = (Checks) itr.next();
                if (ch.getValidity().equals("Available")) {
                    che.add(ch);
                }
            }


            em.getTransaction().commit();
            return che;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }

    public void ModifyCheck(Checks ch) {
        em.getTransaction().begin();
        try {
            ch.setValidity("Cancelled");

            em.merge(ch);

            em.getTransaction().commit();
        } catch (Exception ex) {
            //   em.getTransaction().rollback();
        }


    }
     public ArrayList readNumOfCreditOK(Customer cc) {
        em.getTransaction().begin();

        try {
            ArrayList che = new ArrayList();
            Query q = em.createQuery("SELECT cc FROM Customer cc Where cc.customerid='" + cc.getCustomerId() + "'", Customer.class);
            List result = q.getResultList();
            Iterator itr = result.iterator();
            while (itr.hasNext()) {
                Checks ch = (Checks) itr.next();
                if (ch.getValidity().equals(cc.getNoofchecks())) {
                    che.add(ch);
                }
            }


            em.getTransaction().commit();
            return che;
        } catch (Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();

        }
        return null;
    }
}
